package com.liu.qqRobot.poke.handler;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.liu.common.content.RedisKeyInterface;
import com.liu.common.utils.HtmlToImageUtils;
import com.liu.common.utils.QQClientUtils;
import com.liu.mybatisPlus.poke.entity.base.Poke;
import com.liu.mybatisPlus.poke.entity.base.PokeGroupUserPoke;
import com.liu.mybatisPlus.poke.entity.base.PokeSkill;
import com.liu.mybatisPlus.poke.entity.base.PokeUserPokeSkill;
import com.liu.mybatisPlus.poke.service.PokeGroupUserPokeService;
import com.liu.mybatisPlus.poke.service.PokeService;
import com.liu.mybatisPlus.poke.service.PokeSkillService;
import com.liu.mybatisPlus.poke.service.PokeUserPokeSkillService;
import com.liu.mybatisPlus.q.service.QGroupUserOperationQuantityService;
import com.liu.qqRobot.event.entity.dto.EventReportingDTO;
import com.liu.qqRobot.q.enums.OperationTypeEnum;
import freemarker.template.TemplateException;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.xml.sax.SAXException;

import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Component
public class CatchPokeHandler {

    @Resource
    private PokeService pokeService;

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Resource
    private PokeGroupUserPokeService pokeGroupUserPokeService;

    @Resource
    private QGroupUserOperationQuantityService qGroupUserOperationQuantityService;

    @Resource
    private PokeSkillService pokeSkillService;

    @Resource
    private PokeUserPokeSkillService pokeUserPokeSkillService;

    /**
     * 处理事件
     * @param data 信息内容
     * @param groupId 群号
     * @param userId 发送人QQ号
     * @param type 1:捕捉随机一个宝可梦 2:捕捉指定宝可梦
     */
    public void handler(EventReportingDTO.Message.Data data, Long groupId, Long userId, Boolean isGroup, Integer type) {
        if (groupId == 938354542) {
            Object catchPoke = redisTemplate.opsForHash().get(RedisKeyInterface.CATCH_POKE_TIME_REDIS_KEY, groupId + String.valueOf(userId));
            if (catchPoke != null) {
                String existDay = String.valueOf(catchPoke);
                String nowDay = DateUtil.format(DateUtil.offsetHour(DateUtil.date(), 8), "yyyy-MM-dd");
                if (existDay.equals(nowDay)) {
                    return;
                }
            }
            redisTemplate.opsForHash().put(RedisKeyInterface.CATCH_POKE_TIME_REDIS_KEY, groupId + String.valueOf(userId), DateUtil.format(DateUtil.offsetHour(DateUtil.date(), 8), "yyyy-MM-dd"));
        }
        switch (type) {
            case 1 -> {
                this.catchAnyOne(groupId, userId, isGroup);
            }
            case 2 -> {
                String text = data.getText();
                String pokeName = text.replace("捕捉 ", "");
                this.catchAppoint(pokeName, groupId, userId, isGroup);
            }
        }
    }

    /**
     * 捕捉随机一个宝可梦
     * @param groupId groupId
     * @param userId userId
     * @param isGroup isGroup
     */
    private void catchAnyOne(Long groupId, Long userId, Boolean isGroup) {
        List<Poke> pokeList = pokeService.list();
        Poke poke = pokeList.get(RandomUtil.randomInt(pokeList.size()));
        QueryWrapper<PokeGroupUserPoke> pokeGroupUserPokeQueryWrapper = new QueryWrapper<>();
        pokeGroupUserPokeQueryWrapper.eq("group_id", groupId);
        pokeGroupUserPokeQueryWrapper.eq("user_id", userId);
        pokeGroupUserPokeQueryWrapper.eq("poke_id", poke.getId());
        PokeGroupUserPoke pokeGroupUserPoke = pokeGroupUserPokeService.getOne(pokeGroupUserPokeQueryWrapper);
        if (pokeGroupUserPoke == null) {
            pokeGroupUserPoke = new PokeGroupUserPoke();
            pokeGroupUserPoke.setGroupId(groupId);
            pokeGroupUserPoke.setUserId(userId);
            pokeGroupUserPoke.setPokeId(poke.getId());
            pokeGroupUserPoke.setHp(poke.getHp());
            pokeGroupUserPoke.setAggressivity(poke.getAggressivity());
            pokeGroupUserPokeService.save(pokeGroupUserPoke);
            this.getSkillAndSend(poke, groupId, userId, isGroup, pokeGroupUserPoke);
        } else if (pokeGroupUserPoke.getIsRelease()) {
            // 已放生poke再次捕捉
            pokeGroupUserPoke.setIsRelease(false);
            pokeGroupUserPokeService.updateById(pokeGroupUserPoke);
            this.getSkillAndSend(poke, groupId, userId, isGroup, pokeGroupUserPoke);
        }
    }

    /**
     * 捕捉指定宝可梦
     * @param pokeName pokeName
     * @param groupId groupId
     * @param userId userId
     * @param isGroup isGroup
     */
    private void catchAppoint(String pokeName, Long groupId, Long userId, Boolean isGroup) {
        String pokeIdStr = redisTemplate.opsForValue().get(RedisKeyInterface.ENCOUNTER_POKE_REDIS_KEY + groupId + userId + pokeName);
        if (pokeIdStr == null) {
            return;
        }
        Poke poke = pokeService.getById(pokeIdStr);
        QueryWrapper<PokeGroupUserPoke> pokeGroupUserPokeQueryWrapper = new QueryWrapper<>();
        pokeGroupUserPokeQueryWrapper.eq("group_id", groupId);
        pokeGroupUserPokeQueryWrapper.eq("user_id", userId);
        pokeGroupUserPokeQueryWrapper.eq("poke_id", poke.getId());
        PokeGroupUserPoke pokeGroupUserPoke = pokeGroupUserPokeService.getOne(pokeGroupUserPokeQueryWrapper);
        if (pokeGroupUserPoke == null) {
            pokeGroupUserPoke = new PokeGroupUserPoke();
            pokeGroupUserPoke.setGroupId(groupId);
            pokeGroupUserPoke.setUserId(userId);
            pokeGroupUserPoke.setPokeId(poke.getId());
            pokeGroupUserPoke.setHp(poke.getHp());
            pokeGroupUserPoke.setAggressivity(poke.getAggressivity());
            pokeGroupUserPokeService.save(pokeGroupUserPoke);
            this.getSkillAndSend(poke, groupId, userId, isGroup, pokeGroupUserPoke);
        } else if (pokeGroupUserPoke.getIsRelease()) {
            // 已放生poke再次捕捉
            pokeGroupUserPoke.setIsRelease(false);
            pokeGroupUserPokeService.updateById(pokeGroupUserPoke);
            this.getSkillAndSend(poke, groupId, userId, isGroup, pokeGroupUserPoke);
        }
        redisTemplate.delete(RedisKeyInterface.ENCOUNTER_POKE_REDIS_KEY + groupId + userId + pokeName);
    }

    /**
     * 获取技能并发送QQ信息
     * @param poke poke
     * @param groupId groupId
     * @param userId userId
     * @param isGroup isGroup
     * @param pokeGroupUserPoke pokeGroupUserPoke
     */
    private void getSkillAndSend(Poke poke, Long groupId, Long userId, Boolean isGroup, PokeGroupUserPoke pokeGroupUserPoke) {
        // 通过宝可梦的属性随机获取5个招式
        QueryWrapper<PokeSkill> pokeSkillQueryWrapper = new QueryWrapper<>();
        List<String> pokeAttributeList = new ArrayList<>();
        if (StrUtil.isNotEmpty(poke.getAttribute1())) {
            pokeAttributeList.add(poke.getAttribute1());
        }
        if (StrUtil.isNotEmpty(poke.getAttribute2())) {
            pokeAttributeList.add(poke.getAttribute2());
        }
        pokeSkillQueryWrapper.in("attribute", pokeAttributeList);
        List<PokeSkill> pokeSkillList = pokeSkillService.list(pokeSkillQueryWrapper);
        List<String> pokeSkillNameList = new ArrayList<>();
        List<PokeUserPokeSkill> pokeUserPokeSkillList = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            PokeSkill pokeSkill = pokeSkillList.get(RandomUtil.randomInt(pokeSkillList.size()));
            pokeSkillNameList.add(pokeSkill.getName());
            PokeUserPokeSkill pokeUserPokeSkill = new PokeUserPokeSkill();
            pokeUserPokeSkill.setUserPokeId(pokeGroupUserPoke.getId());
            pokeUserPokeSkill.setSkillId(pokeSkill.getId());
            pokeUserPokeSkillList.add(pokeUserPokeSkill);
            pokeSkillList.remove(pokeSkill);
        }
        // 有可能是放生后重新捕捉，先清空旧招式
        UpdateWrapper<PokeUserPokeSkill> pokeUserPokeSkillUpdateWrapper = new UpdateWrapper<>();
        pokeUserPokeSkillUpdateWrapper.eq("user_poke_id", pokeGroupUserPoke.getId());
        pokeUserPokeSkillService.remove(pokeUserPokeSkillUpdateWrapper);
        pokeUserPokeSkillService.saveBatch(pokeUserPokeSkillList);

        Map<String, Object> templateParam = new HashMap<>();
        templateParam.put("name", poke.getName());
        templateParam.put("attribute1", poke.getAttribute1());
        templateParam.put("attribute2", poke.getAttribute2());
        templateParam.put("imgUrl", /*"/warframe/" +*/ poke.getLocalUrl());
        templateParam.put("pokeSkillNameList", pokeSkillNameList);
        try {
            HtmlToImageUtils.htmlToImage("catchPokeTemplate.html", templateParam, "src/main/resources/picture/catchPoke.png", 1100);
            File file = new File("src/main/resources/picture/catchPoke.png");
            String encode = Base64.encode(file);
            String msg = "[CQ:at,qq=" + userId + "]\n[CQ:image,file=base64://" + encode+ ",type=show,subType=0]";
            QQClientUtils.sendMsg(msg, userId, groupId, isGroup);
            qGroupUserOperationQuantityService.statisticsOperationQuantityByType(groupId, userId, OperationTypeEnum.CATCH_POKE);
        } catch (IOException | ParserConfigurationException | SAXException | TemplateException e) {
            log.error("获取捕捉宝可梦展示模板失败:{}", e.getMessage(), e);
//            QQClientUtils.sendGroupMsg("[CQ:at,qq=" + userId + "]\n获取捕捉宝可梦展示模板失败，请联系制作人", userId, groupId, isGroup);
        }
    }
}
